#pragma once
#include "SerializerTmpl.h"

namespace catan
{
	typedef unsigned int HandleId;

	template<class Type>
	class Handle 
	{
	public:
		template<class TypeOther>
		Handle(const Handle<TypeOther> & handle) : mId(handle.Id()), mType(handle.Get()) {}

		Handle() : mId(0), mType(0){}
		Handle(HandleId id, Type* type) : mId(id), mType(type) {}
		
		//operator Type*() { return mType; }
		Type& operator *() { VALID(mType); return *mType;}
		const Type& operator *() const { VALID(mType); return *mType;}
		const Type* operator ->() const {return mType;}
		Type* operator ->() {return mType;}
		const HandleId Id() const {return mId; }
		bool operator < (const Handle& h) const { return Id() < h.Id(); }
		bool operator == (const Handle& h) const { VALID(!((Id() == h.Id()) ^ (mType == h.mType))); return Id() == h.Id(); }
		operator bool() const {return mType != 0;}

		template <class NewType>
		Handle<NewType> DynamicCast()
		{
			Handle<NewType> ret(mId, dynamic_cast<NewType*>(mType));
			return ret;
		}

		template <class NewType>
		Handle<NewType> StaticCast()
		{
			Handle<NewType> ret(mId, static_cast<NewType*>(mType));
			return ret;
		}

		Type* Get() const { return mType; }

// 		template <class Type, SerializerDirection::Enum isOut, class SerializerTmpl, class ValueType>
// 			friend SerializerTmpl& operator & (SerializerTmpl& ss, Handle<Type>& t) ;
// 	
		template<class Serializer>
		void serialize(Serializer & s, const unsigned int version)
		{
			s & mId;
		}
	private:
		HandleId mId;
		Type* mType;
	};

	/*tstringstream*/
	
// 	template <class Type, SerializerDirection::Enum isOut, class SerializerTmpl, class ValueType>
// 	SerializerTmpl<type, isOut>& operator & (SerializerTmpl<type, isOut>& ss, Handle<ValueType>& t)
// 	{
// 		ss & t.Id();
// 		return ss;
// 	}
// 	
}	
